﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Configuration;
using DirectorRoomHelper.Models;
using System.IO;
using System.Diagnostics;

namespace DirectorRoomHelper.Controls
{
    /// <summary>
    /// Interaction logic for CatalogViewControl.xaml
    /// </summary>
    public partial class CatalogViewControl : UserControl
    {
        public CatalogViewControl()
        {
            InitializeComponent();
            InitializeCateDict();
            this.CatalogTabs = new ObservableCollection<TabItem>();
            this.DataContext = this;
            tc.Visibility = System.Windows.Visibility.Hidden;
            catalogViewToolBar.IsButtonsEnabled = false;
            catalogViewToolBar.IsUpFolderEnabled = false;
            _drhDataContext = new DRH(ConfigurationManager.ConnectionStrings["drhConn"].ConnectionString);
        }

        private void InitializeCateDict()
        {
            _cateNameDict.Add("1", "督查工作");
            _cateNameDict.Add("2", "目标管理和“夺杯竞赛”活动");
            _cateNameDict.Add("3", "县级领导班子工作实绩考核");
            _cateNameDict.Add("4", "县区域经济和乡镇（街区）经济发展");
            _cateNameDict.Add("5", "城乡一体化建设");
            _cateNameDict.Add("6", "项目建设观摩评议");
            _cateNameDict.Add("7", "重点活动组织协调服务");
        }

        #region --- CloseCommand ---

        private Utils.RelayCommand _cmdCloseCommand;
        /// <summary>
        /// Returns a command that closes a TabItem.
        /// </summary>
        public ICommand CloseCommand
        {
            get
            {
                if (_cmdCloseCommand == null)
                {
                    _cmdCloseCommand = new Utils.RelayCommand(
                        param => this.CloseTab_Execute(param),
                        param => this.CloseTab_CanExecute(param)
                        );
                }
                return _cmdCloseCommand;
            }
        }

        /// <summary>
        /// Called when the command is to be executed.
        /// </summary>
        /// <param name="parm">
        /// The TabItem in which the Close-button was clicked.
        /// </param>
        private void CloseTab_Execute(object parm)
        {
            TabItem ti = parm as TabItem;
            if (ti != null)
            {
                Brush bgBrush = FindResource("MyButtonBlueGradientBrush") as Brush;
                TileViewControl content = ti.Content as TileViewControl;
                switch (content.TopParentID.ToString())
                {
                    case "1":
                        btnCate1.Background = bgBrush;
                        break;
                    case "2":
                        btnCate2.Background = bgBrush;
                        break;
                    case "3":
                        btnCate3.Background = bgBrush;
                        break;
                    case "4":
                        btnCate4.Background = bgBrush;
                        break;
                    case "5":
                        btnCate5.Background = bgBrush;
                        break;
                    case "6":
                        btnCate6.Background = bgBrush;
                        break;
                    case "7":
                        btnCate7.Background = bgBrush;
                        break;
                    default:
                        break;
                }

                CatalogTabs.Remove(ti);

                if (CatalogTabs.Count == 0)
                {
                    tc.Visibility = System.Windows.Visibility.Hidden;
                }
            }
        }

        /// <summary>
        /// Called when the availability of the Close command needs to be determined.
        /// </summary>
        /// <param name="parm">
        /// The TabItem for which to determine the availability of the Close-command.
        /// </param>
        private bool CloseTab_CanExecute(object parm)
        {
            //For the sample, the closing of TabItems will only be
            //unavailable for disabled TabItems and the very first TabItem.
            TabItem ti = parm as TabItem;
            if (ti != null)
                //We have a valid reference to a TabItem, so return 
                //true if the TabItem is enabled.
                return ti.IsEnabled;

            //If no reference to a TabItem could be obtained, the command 
            //cannot be executed
            return false;
        }

        #endregion

        private void CateButton_Click(object sender, RoutedEventArgs e)
        {
            if (tc.Visibility == System.Windows.Visibility.Hidden)
            {
                tc.Visibility = System.Windows.Visibility.Visible;
            }

            Button btn = sender as Button;
            btn.Background = FindResource("MyMouseOverOrangeGradientBrush1") as Brush;


            TabItem ti = CatalogTabs.FirstOrDefault(t => (t.Content as TileViewControl).TopParentID.ToString() == btn.Tag.ToString());
            
            if (ti != null)
            {
                ti.Focus();
                return;
            }

            TabItem newTab = new TabItem();
            newTab.Header = _cateNameDict[btn.Tag.ToString()];
            newTab.Tag = btn.Tag;

            RefreshTabItemContent(newTab, CatalogOperationType.ChgFolderIn);

            //newTab.GotFocus += new RoutedEventHandler(newTab_GotFocus);
            //newTab.LostFocus += new RoutedEventHandler(newTab_LostFocus);
            CatalogTabs.Add(newTab); 
            newTab.Focus();
        }


        private void tc_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.OriginalSource is TabControl)
            {
                foreach (TabItem item in e.RemovedItems)
                {
                    string header = item.Header.ToString();
                    if (!item.IsSelected && header.Length > 5)
                    {
                        item.ToolTip = item.Header;
                        item.Header = header.Substring(0, 5) + "...";
                    }
                }

                foreach (TabItem item in e.AddedItems)
                {
                    if (item.Header.ToString().Contains("..."))
                    {
                        item.Header = item.ToolTip;
                        item.ToolTip = null;
                    }

                    int entryID = Convert.ToInt32(item.Tag);
                    if (entryID < 100)
                    {
                        catalogViewToolBar.IsUpFolderEnabled = false;
                    }
                    else
                    {
                        catalogViewToolBar.IsUpFolderEnabled = true;
                    }
                }
            }
        }

        private void tc_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.OldValue == false)
            {
                catalogViewToolBar.IsButtonsEnabled = true;
            }
            else
            {
                catalogViewToolBar.IsButtonsEnabled = false;
            }
        }

        private void catalogViewToolBar_Click(object sender, RoutedEventArgs e)
        {
            MyImageTextButton btn = e.OriginalSource as MyImageTextButton;

            TabItem tab = tc.SelectedItem as TabItem;
            if (tab == null)
            {
                return;
            }
            int entryID = Convert.ToInt32(tab.Tag);

            switch (btn.Tag.ToString())
            {
                case "newfolder":
                    AddFolder(tab);
                    break;
                case "delete":
                    DeleteEntry(tab);
                    break;
                case "adddoc":
                    AddDocFile(tab);
                    break;
                case "upfolder":
                    if (entryID < 100)
                    {
                        return;
                    }
                    var entry = _drhDataContext.CatalogEntry.FirstOrDefault(f => f.ID == entryID);
                    if (entry != null)
                    {
                        tab.Tag = entry.ParentID.ToString();
                        RefreshTabItemContent(tab, CatalogOperationType.ChgFolderOut);
                        if (entry.ParentID < 100)
                        {
                            catalogViewToolBar.IsUpFolderEnabled = false;
                        }
                    }
                    break;
                default:
                    break;
            }

            e.Handled = true;
        }

        private void AddFolder(TabItem tab)
        {
            int parentID = Convert.ToInt32(tab.Tag);

            var entry = _drhDataContext.CatalogEntry.FirstOrDefault(f => f.ID == parentID);
            if (parentID > 100 && entry == null)
            {
                return;
            }
            string currFolder = (entry != null ? entry.Name : _cateNameDict[parentID.ToString()]);

            AddFolderWindow addFolderWindow = new AddFolderWindow();
            addFolderWindow.CurrFolder = currFolder;
            addFolderWindow.ShowDialog();
            string newFolder = addFolderWindow.NewFolder;
            if (newFolder != string.Empty)
            {
                var existed = _drhDataContext.CatalogEntry.FirstOrDefault(f => f.ParentID == parentID && f.Name == newFolder);
                if (existed == null)
                {
                    TileViewControl content = tab.Content as TileViewControl;

                    try
                    {
                        string root = Environment.CurrentDirectory + "\\docs";
                        string relativePath = content.CurrentPath + "/" + newFolder;
                        Directory.CreateDirectory(root + relativePath.Replace("/", "\\\\"));
                    }
                    catch 
                    {
                        MessageBox.Show("创建文件夹失败，目录可能已有同名文件夹存在");
                        return;
                    }

                    _drhDataContext.CatalogEntry.InsertOnSubmit(new CatalogEntry() { Name = newFolder, OrderNo = 0, ParentID = parentID });
                    _drhDataContext.SubmitChanges();
                    RefreshTabItemContent(tab, CatalogOperationType.AddFolder);
                }
                else
                {
                    MessageBox.Show("目录名冲突");
                }
            }
        }

        private void AddDocFile(TabItem tab)
        {
            int parentID = Convert.ToInt32(tab.Tag);

            var entry = _drhDataContext.CatalogEntry.FirstOrDefault(f => f.ID == parentID);
            if (parentID > 100 && entry == null)
            {
                return;
            }

            string currFolder = (entry != null ? entry.Name : _cateNameDict[parentID.ToString()]);
            AddDocFileWindow fileWindow = new AddDocFileWindow();
            fileWindow.CurrFolder = currFolder;

            fileWindow.ShowDialog();
            string filePath = fileWindow.FilePath;
            DateTime fileDate = fileWindow.FileDate ?? DateTime.Now;
            if (filePath != string.Empty)
            {
                string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
                string fileExt = System.IO.Path.GetExtension(filePath).Replace(".", "");
                var existed = _drhDataContext.DocumentFile.FirstOrDefault(f => f.ParentID == parentID && f.FileName == fileName);
                if (existed == null)
                {
                    TileViewControl content = tab.Content as TileViewControl;

                    string destFolder = 
                        System.IO.Path.Combine(Environment.CurrentDirectory + "\\docs", content.CurrentPath.Remove(0, 1).Replace("/", "\\\\"));
                    string destPath = System.IO.Path.Combine(destFolder , System.IO.Path.GetFileName(filePath));
                    try
                    {
                        if (File.Exists(destPath))
                        {
                            MessageBox.Show("文件夹中存在同名文件");
                            return;
                        }

                        if (!System.IO.Directory.Exists(destFolder))
                        {
                            Directory.CreateDirectory(destFolder);
                        }

                        System.IO.File.Copy(filePath, destPath);
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("复制文件失败");
                        return;
                    }

                    fileName = fileName.Replace("'", "");

                    _drhDataContext.DocumentFile.InsertOnSubmit(
                        new DocumentFile() 
                        { 
                            FileName = fileName, 
                            FileType = fileExt, 
                            ParentID = parentID, 
                            DocDate = fileDate, 
                            AddDate = DateTime.Now 
                        });

                    _drhDataContext.SubmitChanges();

                    RefreshTabItemContent(tab, CatalogOperationType.AddFile);
                }
                else
                {
                    MessageBox.Show("该文件已存档");
                }
            }
        }

        private void DeleteEntry(TabItem tab)
        {
            TileViewControl tabContent = tab.Content as TileViewControl;
            ListBox lbx = tabContent.Content as ListBox;
            
            if (lbx.SelectedIndex < 0)
            {
                return;
            }

            TileViewItem tileItem = lbx.SelectedItem as TileViewItem;

            if (tileItem != null)
            {
                if (tileItem.ItemType == TileViewItemType.Folder)
                {
                    var childrenItems = _drhDataContext.CatalogEntry.Where(e => e.ParentID == tileItem.ID);
                    if (childrenItems != null && childrenItems.Count() > 0)
                    {
                        MessageBox.Show("不能删除非空文件夹");
                        return;
                    }
                    else
                    {
                        var msgResult = MessageBox.Show("确定要删除该目录吗？", "提示", MessageBoxButton.YesNo);

                        if (msgResult == MessageBoxResult.Yes)
                        {
                            _drhDataContext.CatalogEntry.DeleteOnSubmit(
                                _drhDataContext.CatalogEntry.FirstOrDefault(e => e.ID == tileItem.ID));
                            _drhDataContext.SubmitChanges();

                            RefreshTabItemContent(tab, CatalogOperationType.DelFolder);
                        }
                    }
                }
                else if (tileItem.ItemType == TileViewItemType.DocFile)
                {
                    var msgResult = MessageBox.Show("确定要删除该文件吗？", "提示", MessageBoxButton.YesNo);

                    if (msgResult == MessageBoxResult.Yes)
                    {
                        _drhDataContext.DocumentFile.DeleteOnSubmit(
                            _drhDataContext.DocumentFile.FirstOrDefault(f => f.ID == tileItem.ID));
                        _drhDataContext.SubmitChanges();

                        RefreshTabItemContent(tab, CatalogOperationType.DelFile);
                    }
                }
            }
        }

        void RefreshTabItemContent(TabItem tab, CatalogOperationType oprType)
        {
            TileViewControl oldContent = tab.Content as TileViewControl;
            TileViewControl content = new TileViewControl();

            if (oldContent != null)
            {
                content.TopParentID = oldContent.TopParentID;
                content.CurrentPath = oldContent.CurrentPath;  //remember first, change below
            }

            content.Items = new ObservableCollection<Models.TileViewItem>();
            int parentID = Convert.ToInt32(tab.Tag);
            if (parentID < 100)
            {
                content.TopParentID = parentID; //er..., remember the top level folder id
            }

            var entry = _drhDataContext.CatalogEntry.FirstOrDefault(c => c.ID == parentID);
            string parentFolderName = entry == null ? string.Empty : entry.Name;

            if (!string.IsNullOrEmpty(parentFolderName))
            {
                if (oprType == CatalogOperationType.ChgFolderIn)
                {
                    content.CurrentPath = oldContent.CurrentPath + "/" + parentFolderName;
                }
                else if (oprType == CatalogOperationType.ChgFolderOut)
                {
                    content.CurrentPath =
                        oldContent.CurrentPath.Remove(oldContent.CurrentPath.LastIndexOf('/'));
                }
            }
            else
            {
                if (parentID < 100)
                {
                    if (oprType == CatalogOperationType.ChgFolderIn 
                        || oprType == CatalogOperationType.ChgFolderOut)
                    {
                        content.CurrentPath = "/" + parentID;
                    }
                }
            }

            var categories = 
                from c in _drhDataContext.CatalogEntry
                where c.ParentID == parentID
                select new TileViewItem() 
                { 
                    ID = c.ID, 
                    Name = c.Name, 
                    ImagePath = "/graphics/subfolder.ico", 
                    ItemType = TileViewItemType.Folder, 
                    RelatedItem = c 
                };

            var docFiles = 
                from f in _drhDataContext.DocumentFile
                where f.ParentID == parentID
                select new TileViewItem() 
                { 
                    ID = f.ID, 
                    Name = f.FileName, 
                    ImagePath = "/graphics/docicon.png", 
                    ItemType = TileViewItemType.DocFile, 
                    RelatedItem = f 
                };

            foreach (var item in categories)
            {
                content.Items.Add(item);
            }

            foreach (var item in docFiles)
            {
                content.Items.Add(item);
            }

            tab.Content = null;
            tab.Content = content;
        }

        private void tc_ItemAction(object sender, RoutedEventArgs e)
        {
            ListBox lbx = e.OriginalSource as ListBox;
            TileViewItem tileItem = lbx.SelectedItem as TileViewItem;

            if (tileItem != null)
            {
                if (tileItem.ItemType == TileViewItemType.Folder)
                {
                    TabItem tab = tc.SelectedItem as TabItem;
                    tab.Tag = tileItem.ID.ToString();
                    RefreshTabItemContent(tab, CatalogOperationType.ChgFolderIn);
                    if (tileItem.ID > 100)
                    {
                        catalogViewToolBar.IsUpFolderEnabled = true;
                    }
                }
                else if (tileItem.ItemType == TileViewItemType.DocFile)
                {
                    DocumentFile docFile = tileItem.RelatedItem as DocumentFile;
                    if (docFile != null)
                    {
                        string docsRoot = Environment.CurrentDirectory + "\\docs\\";
                        TileViewControl tabContent = (tc.SelectedItem as TabItem).Content as TileViewControl;
                        string fileName = docFile.FileName + "." + docFile.FileType;
                        string filePath = 
                            System.IO.Path.Combine(docsRoot + tabContent.CurrentPath.Replace("/", "\\"), fileName);

                        if (System.IO.File.Exists(filePath))
                        {
                            Cursor c = this.Cursor;
                            this.Cursor = Cursors.Wait;
                            Process.Start(filePath);
                            this.Cursor = c;
                        }
                    }
                }
            }

            e.Handled = true;
        }

        private string GetAbsoluteDocsPath(string relativePath)
        {
            if (string.IsNullOrEmpty(relativePath))
            {
                return System.IO.Path.Combine(Environment.CurrentDirectory, "docs");
            }

            return Environment.CurrentDirectory + "\\docs" + relativePath.Replace("/", "\\");
        }

        //public Visibility TabControlVisibility
        //{
        //    get { return (Visibility)GetValue(TabControlVisibilityProperty); }
        //    set 
        //    {
        //        if (CatalogTabs == null || CatalogTabs.Count == 0)
        //        {
        //            SetValue(TabControlVisibilityProperty, Visibility.Hidden); 
        //        }
        //        else
        //        {
        //            SetValue(TabControlVisibilityProperty, Visibility.Visible);
        //        }
        //    }
        //}

        //// Using a DependencyProperty as the backing store for IsTabControlVisible.  This enables animation, styling, binding, etc...
        //public static readonly DependencyProperty TabControlVisibilityProperty =
        //    DependencyProperty.Register("TabControlVisibility", typeof(Visibility), typeof(CatalogViewControl));

        private DRH _drhDataContext;
        public ObservableCollection<TabItem> CatalogTabs { get; private set; }
        private Dictionary<string, string> _cateNameDict = new Dictionary<string, string>();
    }
}
